home *** CD-ROM | disk | FTP | other *** search
- /* xldmem - xlisp dynamic memory management routines */
-
- #ifdef CI_86
- #include "a:stdio.h"
- #include "xlisp.h"
- #endif
-
- #ifdef AZTEC
- #include "a:stdio.h"
- #include "xlisp.h"
- #endif
-
- #ifdef unix
- #include <stdio.h>
- #include <xlisp.h>
- #endif
-
-
-
- /* useful definitions */
-
- #define ALLOCSIZE (sizeof(struct segment) + anodes * sizeof(struct node))
-
-
- /* memory segment structure definition */
-
- struct segment {
- int sg_size;
- struct segment *sg_next;
- struct node sg_nodes[];
- };
-
- /* external variables */
-
- extern struct node *oblist;
- extern struct node *xlstack;
- extern struct node *xlenv;
-
-
- /* external procedures */
-
- extern char *malloc();
- extern char *calloc();
-
-
- /* local variables */
-
- int anodes,nnodes,nsegs,nfree,gccalls;
- static struct segment *segs;
- static struct node *fnodes;
-
-
- /**********************************
- * newnode - allocate a new node *
- **********************************/
-
- struct node *newnode(type)
- int type;
- {
- struct node *nnode;
-
- /* get a free node */
- if ((nnode = fnodes) == NULL) {
- gc();
- if ((nnode = fnodes) == NULL)
- xlfail("insufficient node space");
- }
-
- /* unlink the node from the free list */
- fnodes = nnode->n_right;
- nfree -= 1;
-
- /* initialize the new node */
- nnode->n_type = type;
- nnode->n_left = NULL;
- nnode->n_right = NULL;
-
- /* return the new node */
- return (nnode);
- }
-
-
- /*****************************************************************************
- * stralloc - allocate memory for a string adding a byte for the terminator *
- *****************************************************************************/
-
- char *stralloc(size)
- int size;
- {
- char *sptr;
-
- /* allocate memory for the string copy */
- if ((sptr = malloc(size+1)) == NULL) {
- gc();
- if ((sptr = malloc(size+1)) == NULL)
- xlfail("insufficient string space");
- }
-
- /* return the new string memory */
- return (sptr);
- }
-
-
- /**************************************************
- * strsave - generate a dynamic copy of a string *
- **************************************************/
-
- char *strsave(str)
- char *str;
- {
- char *sptr;
-
- /* */
- sptr = stralloc(strlen(str));
- strcpy(sptr,str);
-
- /* return the new string */
- return (sptr);
- }
-
-
- /*********************************
- * strfree - free string memory *
- *********************************/
-
- strfree(str)
- char *str;
- {
- free(str);
- }
-
-
- /*************************
- * gc - garbage collect *
- *************************/
-
- static gc()
- {
- unmark(); /* Unmark all nodes */
-
- #ifdef DEBUG
- xldbgmsg("\n\tOBLIST mark");
- mark(oblist);
- xldbgmsg("\n\tSTACK mark");
- mark(xlstack);
- xldbgmsg("\n\tENVIRONMENT");
- mark(xlenv);
- #else
- mark(oblist); /* Mark all accessible nodes */
- mark(xlstack);
- mark(xlenv);
- #endif
-
- sweep(); /* Sweep up the grabage */
-
- if (fnodes == NULL) /* Allocate more if necessary */
- addseg();
-
- gccalls += 1;
- }
-
-
- /******************************
- * unmark - unmark each node *
- ******************************/
-
- static unmark()
- {
- struct node *n = xlstack;
-
- while (n != NULL) /* Unmark the stack */
- {
- n->n_flags &= ~(MARK | LEFT);
- n = n->n_listnext;
- }
- }
-
- /*************************************
- * mark - mark all accessible nodes *
- *************************************/
-
- static mark(ptr)
- struct node *ptr;
- {
- struct node *this,*prev,*tmp;
-
- if (ptr == NULL) /* Return on null */
- return;
-
- prev = NULL; /* Initialize */
- this = ptr;
-
- while (TRUE) /* Mark this list */
- {
- while (TRUE) /* Descend as far as we can */
- {
- if (this->n_flags & MARK) /* Node already marked ? */
- break;
- else /* NO : mark it and its descendents */
- {
-
- #ifdef DEBUG
- xldump(this);
- #endif
- this->n_flags |= MARK; /* This node ...*/
-
- if (left(this)) /* .. the left sublist */
- {
- this->n_flags |= LEFT;
- tmp = prev;
- prev = this;
- this = prev->n_left;
- prev->n_left = tmp;
- }
- else
- if (right(this)) /* .. the right sublist */
- {
- this->n_flags &= ~LEFT;
- tmp = prev;
- prev = this;
- this = prev->n_right;
- prev->n_right = tmp;
- }
- else
- break;
- }
- }
-
- while (TRUE) /* Backup to last restart point */
- {
- if (prev == NULL) /* Finished yet ? */
- return;
-
- if (prev->n_flags & LEFT) /* Coming from left side ? */
- {
- if (right(prev))
- {
- prev->n_flags &= ~LEFT;
- tmp = prev->n_left;
- prev->n_left = this;
- this = prev->n_right;
- prev->n_right = tmp;
- break;
- }
- else
- {
- tmp = prev;
- prev = tmp->n_left;
- tmp->n_left = this;
- this = tmp;
- }
- }
- else /* came from the right side */
- {
- tmp = prev;
- prev = tmp->n_right;
- tmp->n_right = this;
- this = tmp;
- }
- }
- }
- }
-
-
- /*******************************************************************
- * sweep - sweep all unmarked nodes and add them to the free list *
- *******************************************************************/
-
- static sweep()
- {
- struct segment *seg;
- struct node *n;
- int i;
-
- fnodes = NULL; /* Empty the free list */
- nfree = 0;
-
- /* add all unmarked nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next)
- for (i = 0; i < seg->sg_size; i++)
- if (!((n = &seg->sg_nodes[i])->n_flags & MARK))
- {
- switch (n->n_type)
- {
- case STR:
- if (n->n_strtype == DYNAMIC && n->n_str != NULL)
- strfree(n->n_str);
- break;
-
- case SYM:
- if (n->n_symname != NULL)
- strfree(n->n_symname);
- break;
-
- #ifdef KEYMAPCLASS
- case KMAP:
- xlkmfree(n);
- break;
- #endif
- }
-
- n->n_type = FREE;
- n->n_left = NULL;
- n->n_right = fnodes;
- fnodes = n;
- nfree += 1;
- }
- else
- n->n_flags &= ~MARK;
- }
-
-
- /***************************************************
- * addseg - add a segment to the available memory *
- ***************************************************/
-
- static int addseg()
- {
- struct segment *newseg;
- int i;
-
- /* allocate a new segment */
- if ((newseg = (struct segment *) calloc(1,ALLOCSIZE)) != NULL)
- {
- newseg->sg_size = anodes; /* Initialize the new segment */
- newseg->sg_next = segs;
- segs = newseg;
- /* add each new node to the free list */
- for (i = 0; i < newseg->sg_size; i++)
- {
- newseg->sg_nodes[i].n_right = fnodes;
- fnodes = &newseg->sg_nodes[i];
- }
-
- nnodes += anodes; /* Update the statistics */
- nfree += anodes;
- nsegs += 1;
-
- return (TRUE); /* return success */
- }
- else
- return (FALSE);
- }
-
-
- /************************************
- * left - check for a left sublist *
- ************************************/
-
- static int left(n)
- struct node *n;
- {
- switch (n->n_type)
- {
- case SYM:
- case SUBR:
- case INT:
- case STR:
- case FPTR:
- case REAL:
- return (FALSE);
-
- #ifdef KEYMAPCLASS
- case KMAP:
- xlkmmark(n);
- return (FALSE);
- #endif
-
- case LIST:
- case OBJ:
- return (n->n_left != NULL);
-
- default:
- printf("bad node type (%d) found during left scan\n",n->n_type);
- exit();
- }
- }
-
-
- /**************************************
- * right - check for a right sublist *
- **************************************/
-
- static int right(n)
- struct node *n;
- {
- switch (n->n_type)
- {
- case SUBR:
- case INT:
- case REAL:
- case STR:
- case FPTR:
- case KMAP:
- return (FALSE);
-
- case SYM:
- case LIST:
- case OBJ:
- return (n->n_right != NULL);
-
- default:
- printf("bad node type (%d) found during right scan\n",n->n_type);
- exit();
- }
- }
-
-
- /************************************
- * stats - print memory statistics *
- ************************************/
-
- static stats()
- {
- printf("\nNodes: %d\n",nnodes);
- printf("Free nodes: %d\n",nfree);
- printf("Segments: %d\n",nsegs);
- printf("Allocate: %d\n",anodes);
- printf("Collections: %d\n\n",gccalls);
- }
-
-
- /*****************************************************
- * fgc - xlisp function to force garbage collection *
- *****************************************************/
-
- static struct node *fgc(args)
- struct node *args;
- {
- xllastarg(args); /* No arguments */
- gc(); /* Collect that garbage */
- return (NULL);
- }
-
-
- /*******************************************************
- * fexpand - xlisp function to force memory expansion *
- *******************************************************/
-
- static struct node *fexpand(args)
- struct node *args;
- {
- struct node *val;
- int n,i;
-
- /* get new number to allocate */
- n = (args == NULL) ? 1 : xlevmatch(INT, &args)->n_int;
- xllastarg(args); /* No more arguments */
-
- for (i = 0; i < n; i++) /* Allocate more segments */
- if (!addseg())
- break;
-
- val = newnode(INT); /* Return number of segments added */
- val->n_int = i;
- return (val);
- }
-
- /*******************************************************************
- * falloc - xlisp function to set the number of nodes to allocate *
- *******************************************************************/
-
- static struct node *falloc(args)
- struct node *args;
- {
- struct node *val;
- int n,oldn;
-
- n = xlevmatch(INT,&args)->n_int; /* new number to allocate */
- xllastarg(args); /* No more arguments */
-
- oldn = anodes; /* Set new number */
- anodes = n;
-
- val = newnode(INT); /* Return old value */
- val->n_int = oldn;
- return (val);
- }
-
-
- /*****************************************************
- * fmem - xlisp function to print memory statistics *
- *****************************************************/
-
- static struct node *fmem(args)
- struct node *args;
- {
- xllastarg(args); /* No arguments */
- stats(); /* Print statistics */
- return (NULL);
- }
-
-
- /******************************************************
- * xldmeminit - initialize the dynamic memory module *
- ******************************************************/
-
- xldmeminit()
- {
- anodes = NNODES; /* Default number of nodes */
- nnodes = nsegs = nfree = gccalls = 0;
-
- xlsubr("gc",fgc); /* Define some xlisp functions */
- xlsubr("expand",fexpand);
- xlsubr("alloc",falloc);
- xlsubr("mem",fmem);
- }